import { postGetallindustries } from "@/apis/endpoint/home";
import { Industry } from "@/apis/endpoint/model";
import GpContainer from "@/components/GpContainer";
import GpFontIcon from "@/components/GpFontIcon";
import { GpSearchInput } from "@/components/GpSeachInput";
import GpVerticelLine from "@/components/GpVerticelLine";
import { useNavigateEventChannel } from "@/hooks/useNavigateEventChannel";
import { withCache } from "@/utils/cache";
import { debounce, removeItem } from "@/utils/helper";
import { navigate } from "@/utils/navigation";
import { Button, ScrollView, Text, View } from "@tarojs/components";
import { useRouter } from "@tarojs/taro";
import clsx from "clsx";
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useImmer } from "use-immer";

type IndustryEntry = Industry & {
  parent?: {id: number; name: string}
}
type IndustryGroup = Expandable<IndustryEntry>
type IndustryGroupMap = {
  [rid: number]: IndustryGroup
}

type SearchItem = {
  node: React.ReactNode
  item: IndustryEntry
}

type RouteParams = {
  industryids?: string
}
export default function Index() {
  const router = useRouter<RouteParams>()
  const industryIds = router.params.industryids ? router.params.industryids.split(",").map(Number) : null
  const { eventChannel } = useNavigateEventChannel()
  const [rootNodes, setRootNodes] = useState<Industry[]>([])
  const availableIndustrys = useRef<IndustryEntry[]>([])
  const industryGroupMap = useRef<IndustryGroupMap>({})
  const [currentGroup, setCurrentGroup] = useState<IndustryGroup>()
  const [selects, setSelects] = useImmer<Array<IndustryEntry>>([])
  const selectSum = useMemo(() => {
    const sumMap: {[rid: number]: number} = {}
    selects.forEach(l => {
      sumMap[l.parentId] ??= 0
      sumMap[l.parentId]++
    })
    return sumMap
  }, [selects])
  const [search, setSearch] = useState("")
  const [searchList, setSearchList] = useState<SearchItem[]>([])
  const triggerSearch = useCallback(debounce(300, (value: string) => {
    const text = value.trim()
    if (text.length === 0) {
      setSearchList([])
      return;
    }
    const regEx = new RegExp(`(${text})`, "i");
    const nodes = availableIndustrys.current
    .filter(item => regEx.test(item.name))
    .map(item => {
      const spliter = React.createElement(Text, {
        className: "text-theme"
      }, text)
      const parts = item.name.split(regEx).map<React.ReactNode>(part => {
        if (part === text) return spliter
        return part
      })
      return {
        node: parts,
        item
      }
    })
    setSearchList(nodes)
  }), [rootNodes])
  useEffect(() => {
    withCache("postGetallindustries", () => postGetallindustries().send())
    .then(list => {
      const roots: Industry[] = []
      list.forEach(item => {
        if (item.parentId === 0) {
          roots.push(item)
        } else {
          availableIndustrys.current.push(item)
        }
      })
      for (let i = 0; i < roots.length; i++) {
        const r = roots[i]
        industryGroupMap.current[r.id] ??= {
          item: r,
          children: []
        }
        for (let k = 0; k < availableIndustrys.current.length; k++) {
          const l = availableIndustrys.current[k]
          if (r.id === l.parentId) {
            l.parent = { id: r.id, name: r.name }
            industryGroupMap.current[r.id].children.push({
              item: l,
              children: []
            })
          }
        }
      }
      if (industryIds) {
        setSelects(industryIds.map(id => availableIndustrys.current.find(l => l.id === id)!))
      }
      setCurrentGroup(industryGroupMap.current[roots[0].id])
      setRootNodes(roots)
    })
  }, [])
  function handleSearchChange(value: string) {
    setSearch(value)
    triggerSearch(value)
  }
  function handleTapItem(item: IndustryEntry) {
    if (~selects.findIndex(l => l.id === item.id)) {
      handleRemoveSelect(item)
    } else {
      setSelects(draft => {
        draft.push(item)
      })
    }
    handleSearchChange("")
  }
  function handleRemoveSelect(item: IndustryEntry) {
    setSelects(draft => {
      removeItem(draft, l => l.id === item.id)
    })
  }
  function handleSave() {
    process.env.NODE_ENV === "development" && console.log('选择了行业:', selects)
    if (eventChannel) {
      eventChannel.emit("chooseIndustry", selects)
    }
    navigate()
  }
  function renderIndustryList() {
    return (
      <Fragment>
        <View className="flex-1 h-0 box-border flex flex-row items-stretch">
          <View className="h-full w-[252px] flex-none bg-[#F4F6FC]">
            <ScrollView
              style={{height: "100%"}}
              scrollY
              scrollWithAnimation
            >
              {
                rootNodes.map(item => (
                  <View key={item.id} className={clsx("flex flex-row items-center relative box-border w-full h-[100px] pl-[32px] pr-[28px]", {
                    "bg-white": item.id === currentGroup?.item.id
                    })}
                    onClick={() => setCurrentGroup(industryGroupMap.current[item.id])}
                  >
                    {
                      item.id === currentGroup?.item.id
                      ? <GpVerticelLine width={8} height={64} className="rounded-[4px] absolute left-0 my-auto" />
                      : null
                    }
                    <Text className={clsx("text-[28px]", item.id === currentGroup?.item.id ? "text-theme font-bold" : "text-primary font-normal")}>
                      {item.name}
                    </Text>
                    {
                      selectSum[item.id]
                      ? (
                        <View className="size-[32px] bg-theme rounded-[50%] flex justify-center items-center flex-none ml-[24px]">
                          <Text className="text-white text-[24px]">{selectSum[item.id]}</Text>
                        </View>
                      ) : null
                    }
                  </View>
                ))
              }
            </ScrollView>
          </View>
          <View className="h-full flex-1 w-0 bg-white">
            <ScrollView
              style={{height: "100%"}}
              scrollY
              scrollWithAnimation
            >
              <View className="box-border px-[32px]">
                <View className="grid grid-cols-2 gap-[18px]">
                  {
                    currentGroup?.children.map(l => (
                      <View key={l.item.id} onClick={() => handleTapItem(l.item)}
                      className={clsx("flex flex-row justify-center items-center rounded-[16px] px-[8px] py-[24px]", selects.findIndex(m => m.id === l.item.id) === -1 ? "bg-[#F7F8FA] text-primary" : "bg-theme/8 text-theme font-bold")}>
                        <Text className="text-[28px] text-center">
                          {l.item.name}
                        </Text>
                      </View>
                    ))
                  }
                </View>
              </View>
            </ScrollView>
          </View>
        </View>
        {renderSelects()}
      </Fragment>
    )
  }
  function renderSearchList() {
    return (
      <View className="box-border px-[32px] flex-1 h-0 overflow-y-auto">
        {
          searchList.map(item => (
            <View onClick={() => handleTapItem(item.item)} className="flex flex-col gap-[16px] justify-center h-[138px] text-primary text-[32px] border-b-2 border-solid border-b-[#EEEEEE]">
              <Text>{item.node}</Text>
              <Text className="text-third text-[24px]">{item.item.parent?.name}-{item.item.name}</Text>
            </View>
          ))
        }
      </View>
    )
  }
  function renderSelects() {
    return (
      <View className="flex-none bg-white">
        <View className="flex flex-row items-stretch box-border h-[80px]">
          <Text className="flex-none pl-[32px] pr-[20px] text-secondary text-[28px] leading-[80px]">
            已选
          </Text>
          <ScrollView
            style={{width: 0, flex: 1, display: "flex", flexDirection: "row", alignItems: "center", gap: 16}}
            scrollX
            scrollWithAnimation
            enableFlex
          >
            {
              selects.map(item => (
                <View key={item.id} className="flex-none flex flex-row items-center gap-[8px] box-border rounded-[28px] bg-theme/6 h-[56px] px-[24px]">
                  <Text className="text-theme text-[28px]">{item.name}</Text>
                  <GpFontIcon name="icon-guanbi" className="text-theme" size={24} onClick={() => handleRemoveSelect(item)}/>
                </View>
              ))
            }
          </ScrollView>
        </View>
        <View className="pt-[16px] px-[32px] pb-[32px] box-border">
          <Button className="w-full h-[80px] flex justify-center items-center rounded-[64px] bg-theme" onClick={handleSave}>
            <Text className="text-white text-[32px]">保存</Text>
          </Button>
        </View>
      </View>
    )
  }
  return (
    <GpContainer className="bg-white box-border h-screen flex flex-col">
      <View className="px-[32px] pb-[24px] flex flex-col flex-none">
        <Text className="text-primary font-bold text-[48px] leading-[48px] pt-[20px]">选择期望行业</Text>
        <GpSearchInput
          className="mt-[32px]"
          placeholder="搜索行业名称"
          value={search}
          onChange={handleSearchChange}
        />
      </View>
      { searchList.length > 0 ? renderSearchList() : renderIndustryList() }
    </GpContainer>
  )
}
